#include "LOpenGL.h"
#include "Window.h"
#include "WindowDebug.h"

Window::Window(int width, int height, const std::string& title, bool fullscreen, bool debug) :
m_width(width),
m_height(height),
m_title(title),
m_isFullScreen(fullscreen),
m_isDebug(debug),
m_isCloseRequested(false)
{
	if (!glfwInit())
	{
		fprintf(stderr, "ERROR: could not start GLFW3\n");
		return;
	}

	// uncomment these lines if on Apple OS X - Setting minimum OpenGL version to use
	/*glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 2);
	glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
	glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);*/

	if (fullscreen)
	{
		GLFWmonitor* monitor = glfwGetPrimaryMonitor();
		const GLFWvidmode* vmode = glfwGetVideoMode(monitor);
		m_window = glfwCreateWindow(vmode->width, vmode->height, "3D Game Engine", NULL, NULL);
	}
	else m_window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL);

	if (!m_window)
	{
		fprintf(stderr, "ERROR: could not open window with GLFW3\n");
		glfwTerminate();
		return;
	}

	glfwMakeContextCurrent(m_window);

	glewExperimental = GL_TRUE;
	GLenum res = glewInit();
	if (res != GLEW_OK)
	{
		fprintf(stderr, "ERROR: could not start GLEW --> %s\n", glewGetErrorString(res));
		return;
	}

	//DEBUG - Log useful info
	if (debug)
	{
		const GLubyte* vendor;
		const GLubyte* renderer;
		const GLubyte* version;
		const GLubyte* shadingLanguageVersion;

		m_windowDebug = new WindowDebug(m_window);

		assert(m_windowDebug->restart_gl_log());
		// start GL context and O/S window using the GLFW helper library
		m_windowDebug->gl_log("starting GLFW\n%s\n", glfwGetVersionString());
		// register the error call-back function that we wrote, above
		//glfwSetErrorCallback(glfw_error_callback);
		vendor = glGetString(GL_VENDOR);
		renderer = glGetString(GL_RENDERER);
		version = glGetString(GL_VERSION);
		shadingLanguageVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);
		printf("Vendor: %s\n", vendor);
		printf("Renderer: %s\n", renderer);
		printf("OpenGL version supported: %s\n", version);
		printf("GLSL Version: %s\n", shadingLanguageVersion);
		m_windowDebug->log_gl_params();
	}
}

Window::~Window()
{
	glfwTerminate();
}

void Window::Update()
{
	//while(!glfwWindowShouldClose(m_window))
	while (!IsClosedRequested())
	{
		if (m_isDebug) m_windowDebug->_update_fps_counter();

		glfwPollEvents();

		if (GLFW_PRESS == glfwGetKey(m_window, GLFW_KEY_ESCAPE))
		{
			//glfwSetWindowShouldClose(m_window, 1);
			m_isCloseRequested = true;
		}

		glfwSwapBuffers(m_window);	//Change later ...
	}
}

void Window::SwapBuffers()
{
	glfwSwapBuffers(m_window);
}

bool Window::IsClosedRequested() const
{
	return m_isCloseRequested;
}

int Window::GetWidth() const
{
	return m_width;
}

int Window::GetHeight() const
{
	return m_height;
}

float Window::GetAspect() const
{
	return (float)m_width / (float)m_height;
}

const std::string& Window::GetTitle() const
{
	return m_title;
}

GLFWwindow* Window::GetGLFWwindow() const
{
	return m_window;
}

